﻿using System;
using System.Diagnostics;
using System.Linq;
using Medianamik.Core;
using Medianamik.Core.DAL.Repositories;
using Medianamik.Core.Sugar;
using Medianamik.Core.Synchronization;
using NUnit.Framework;
using Medianamik.Tests.Common;

namespace Medianamik.Tests.Performance
{
    [TestFixture]
    [Ignore] //Les types sont chargés en mémoire ce qui rend ces tests plus ou moins utilies
        //Il n'existe présentement aucun moyen de charger (eager load) un NodeType à partir de la BD
    public class NodeTypeManagerTest
    {
        private static readonly Guid SimpleTypeId = new Guid("fc046a24-1ce7-43cb-9ad6-6b1cb7cc1f72");
        private static readonly Stopwatch TimeWatcher = new Stopwatch();
        private const int NumberOfInsertions = 100;
        private const string ComplexTypeFile = "ComplexType.txt";
        private const string SimpleType = "SimpleType.txt";
        private static readonly NodeTypeRepository Repository = new NodeTypeRepository();

        [TestFixtureSetUp]
        public void TestFixtureSetUp()
        {
            Utilities.RestoreDatabase("RestoreCS");
        }

        [SetUp]
        public void SetUp()
        {
            //Load caches
            var type = NodeTypeManager.GetNodeType(SimpleTypeId);
        }

        [TestFixtureTearDown]
        public void TestFixtureTearDown()
        {
            Utilities.RestoreDatabase("RestoreCS");
        }

        [TearDown]
        public void TearDown()
        {
            TimeWatcher.Reset();
        }

        [Test]
        public void Time_required_for_saving_simple_type()
        {
            SaveType(CreateNewTypeFromFile(SimpleType));

            Assert.That(TimeWatcher.ElapsedMilliseconds, Is.LessThan(1));
        }

        [Test]
        public void Average_time_required_for_saving_100_simple_types()
        {
            for (var i = 0; i < NumberOfInsertions; i++)
                SaveType(CreateNewTypeFromFile(SimpleType));

            Assert.That(TimeWatcher.ElapsedMilliseconds / NumberOfInsertions, Is.LessThan(1));
        }

        [Test]
        public void Time_required_for_saving_complex_type()
        {
            SaveType(CreateNewTypeFromFile(ComplexTypeFile));

            Assert.That(TimeWatcher.ElapsedMilliseconds, Is.LessThan(1));
        }

        [Test]
        public void Average_time_required_for_saving_100_complex_types()
        {
            for (var i = 0; i < NumberOfInsertions; i++)
                SaveType(CreateNewTypeFromFile(ComplexTypeFile));

            Assert.That(TimeWatcher.ElapsedMilliseconds / NumberOfInsertions, Is.LessThan(1));
        }

        [Test]
        public void Time_required_for_querying_simple_type()
        {
            SaveType(CreateNewTypeFromFile(SimpleType));

            Assert.That(TimeWatcher.ElapsedMilliseconds, Is.LessThan(1));
        }

        [Test]
        public void Average_time_required_for_querying_100_simple_types()
        {
            for (var i = 0; i < NumberOfInsertions; i++)
                SaveType(CreateNewTypeFromFile(SimpleType));

            Assert.That(TimeWatcher.ElapsedMilliseconds / NumberOfInsertions, Is.LessThan(1));
        }

        [Test]
        public void Time_required_for_querying_complex_type()
        {
            SaveType(CreateNewTypeFromFile(ComplexTypeFile));

            Assert.That(TimeWatcher.ElapsedMilliseconds, Is.LessThan(1));
        }

        [Test]
        public void Average_time_required_for_querying_100_complex_types()
        {
            for (var i = 0; i < NumberOfInsertions; i++)
                SaveType(CreateNewTypeFromFile(ComplexTypeFile));

            Assert.That(TimeWatcher.ElapsedMilliseconds / NumberOfInsertions, Is.LessThan(1));
        }

        private void SaveType(NodeType type)
        {
            TimeWatcher.Start();
            NodeTypeManager.SaveType(type);
            TimeWatcher.Stop();
        }

        private NodeType CreateNewTypeFromFile(string file)
        {
            var json = Serialization.GetJsonFromFile(file);
            var recordTypes = json.FromJson<RecordType>();
            var id = Guid.NewGuid();

            return recordTypes.First().Convert(null, id, id.ToString("N").Substring(0, 6));
        }

        private NodeType QueryNodeTypeById(Guid typeId)
        {
            return Repository.GetById(typeId);
        }
    }
}
